1 module hip.gui.scroll_area;
2 import hip.gui.widget;
3 import hip.gui.button;
4 
5 
6 interface IRawScrollable
7 {
8     void onRawScroll(float[3] scroll);
9 }
10 
11 class ScrollArea : Widget, IRawScrollable
12 {
13     private static IWidgetRenderer DebugRenderer()
14     {
15         import hip.api.graphics.g2d.renderer2d;
16         __gshared DebugWidgetRenderer dbgRenderer;
17         if(dbgRenderer is null) dbgRenderer = new DebugWidgetRenderer(HipColor(85,85,85,85));
18         return dbgRenderer;
19     }
20     private IWidgetRenderer renderer;
21     private float scrollRate = -10, currentScroll = 0, lastScroll = 0;
22 
23     this(int width, int height)
24     {
25         this.width = width;
26         this.height = height;
27         renderer = DebugRenderer();
28     }
29 
30     override Bounds getWorldBounds(){return Bounds(worldTransform.x, worldTransform.y, width, height);}
31     void setRenderer(IWidgetRenderer renderer)
32     {
33         assert(renderer !is null);
34         this.renderer = renderer;
35     }
36 
37     void setScrollRate(float rate)
38     {
39         this.scrollRate = rate;
40     }
41 
42     void setScroll(float scroll)
43     {
44         lastScroll = currentScroll;
45         currentScroll = scroll;
46         foreach(ch; children)
47             ch.onScroll([0,currentScroll,0], [0,lastScroll,0]);
48     }
49 
50     void onRawScroll(float[3] scroll)
51     {
52         import hip.api;
53         setScroll(currentScroll + scroll[1]*scrollRate);
54     }
55 
56     override void onRender()
57     {
58         import hip.api.graphics.g2d.renderer2d;
59 
60         setStencilTestingEnabled(true);
61         setStencilTestingFunction(HipStencilTestingFunction.Always, 1, 0xFF);
62         setStencilOperation(HipStencilOperation.Keep, HipStencilOperation.Keep, HipStencilOperation.Replace);
63         setRendererColorMask(0,0,0,0);
64         fillRectangle(worldTransform.x, worldTransform.y, width, height);
65         setRendererColorMask(1,1,1,1);
66         setStencilTestingFunction(HipStencilTestingFunction.Equal, 1, 0xFF);
67         renderer.render(worldTransform.x, worldTransform.y, width, height);
68         foreach(ch; children)
69             ch.render();
70 
71         setStencilTestingEnabled(false);
72     }
73 }
74 
75 import hip.gui.linear_layout;
76 import hip.gui.group;
77 class ScrollBar : LinearLayout
78 {
79     private
80     {
81         Button backward;
82         Button thumb;
83         Button forward;
84     }
85 
86     ///Used to keep the layout size fixed
87     private Widget thumbFixer;
88     private int barSize = 50;
89     private int barRate = 1;
90     private float barScale = 1;
91     private int[2] buttonsDimensions;
92 
93     void setButtonsSize(int width, int height)
94     {
95         forward.width  = backward.width  = width;
96         forward.height = backward.height = height;
97     }
98 
99     void setBarSize(int size)
100     {
101         barSize = size;
102         setDimensionFromDirection(size);
103     }
104 
105     void setTarget(int* target)
106     {
107         backward.setOnClick((){*target = *target - barRate;});
108         forward.setOnClick((){*target = *target + barRate;});
109     }
110 
111     private void setDimensionFromDirection(int dimensionSize)
112     {
113         if(dir == LinearLayout.Direction.horizontal)
114         {
115             thumb.width = cast(int)(dimensionSize * barScale);
116             thumbFixer.width = dimensionSize;
117         }
118         else
119         {
120             thumb.height = cast(int)(dimensionSize * barScale);
121             thumbFixer.height = dimensionSize;
122         }
123     }
124 
125     void setBarScale(int itemsShowing, int itemsCount)
126     {
127         barScale = cast(float)itemsShowing / itemsCount;
128         setDimensionFromDirection(this.barSize);
129     }
130 
131     this(LinearLayout.Direction direction)
132     {
133         setDirection(direction);
134         thumbFixer = new Group();
135         thumbFixer.addChild(thumb = new Button(0,0, 50, 50));
136         backward = new Button(0,0, 50, 50);
137         forward = new Button(0,0, 50, 50);
138 
139         addChild(backward, thumbFixer, forward);
140     }
141 }